
package todolist.util;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;
import todolist.personalization.ErrorMessages;
import todolist.personalization.TaskFieldCustomizer;
import todolist.util.FieldFormatter;

/*
 * Reference: http://www.rgagnon.com/javadetails/java-0024.html
 */

/**
 * For reading/writing application configuration data from file. Singleton.
 * Caller should check for error once before assuming properties are successfully loaded.
 * Currently, only todolist.util.Email depends on this class.
 * @author YouLi
 * @author Ivan
 */
public class ConfigFileIO {
	
	// handle singleton instance

	private static ConfigFileIO _objConfigFileIO;
	
	public static ConfigFileIO getInstance() {
		if (_objConfigFileIO == null)
			_objConfigFileIO = new ConfigFileIO();
		return _objConfigFileIO;
	}
	
	private static final String CONFIG_FILENAME = "config.props";

	private static final String CONFIG_FIELD_SENDER_HOST = "SenderHost";
	private static final String CONFIG_FIELD_SENDER_PORT = "SenderPort";
	private static final String CONFIG_FIELD_SENDER_EMAIL_ADDRESS = "SenderEmail";
	private static final String CONFIG_FIELD_SENDER_PASSWORD = "SenderPassword";
	private static final String CONFIG_FIELD_RECEIVER_EMAIL_ADDRESS = "ReceiverEmail";
	private static final String CONFIG_FIELD_TIMEOUT = "Timeout";
	
	// member attributes

	private String _strSendingHost;
	private String _strSendingPort;
	private String _strSendingEmailAdd;
	private String _strSendingPassword;
	private String _strReceivingEmailAdd;
	private int _intTimeout;
	
	private String _strError;
	
	private ConfigFileIO () {
		_strSendingHost = null;
		_strSendingPort = null;
		_strSendingEmailAdd = null;
		_strSendingPassword = null;
		_strReceivingEmailAdd = null;
		_intTimeout = 0;
		readProperties();
	}
	
	// private methods
	
	/**
	 * Read all properties from file to memory and returns error message if any.
	 */
	private void readProperties() {
		Properties objProperties = new Properties();
		String strTimeout = null;
		try {
			objProperties.load(new FileInputStream(CONFIG_FILENAME));
			_strSendingHost = objProperties.getProperty(CONFIG_FIELD_SENDER_HOST);
			_strSendingPort = objProperties.getProperty(CONFIG_FIELD_SENDER_PORT);
			_strSendingEmailAdd = objProperties.getProperty(CONFIG_FIELD_SENDER_EMAIL_ADDRESS);
			_strSendingPassword = objProperties.getProperty(CONFIG_FIELD_SENDER_PASSWORD);
			_strReceivingEmailAdd = objProperties.getProperty(CONFIG_FIELD_RECEIVER_EMAIL_ADDRESS);
			strTimeout = objProperties.getProperty(CONFIG_FIELD_TIMEOUT);
		} catch (FileNotFoundException objEx) {
			_strError = ErrorMessages.ERR_CONFIG_FILE_NOT_FOUND;
		} catch (IOException objEx) {
			_strError = ErrorMessages.ERR_CONFIG_FILE_UNABLE_TO_OPEN;
		}
		if (_strSendingHost == null || _strSendingPort == null ||
			_strSendingEmailAdd == null || _strSendingPassword == null ||
			_strReceivingEmailAdd == null || strTimeout == null) {
			_strError = ErrorMessages.ERR_CONFIG_FILE_MISSING_PROPERTIES;
			return;
		}
		try {
			_intTimeout = Integer.parseInt(strTimeout);
		} catch (NumberFormatException objEx) {
			_strError = ErrorMessages.ERR_CONFIG_FILE_MISSING_PROPERTIES;
		}
	}
	
	/**
	 * Used by toString to format each field's spacing.
	 */
	private void insertFieldLine(StringBuffer pobjSB, String pstrFieldHeader, String pstrFieldData) {
		FieldFormatter objFormatter = new FieldFormatter();
		objFormatter.addField(pstrFieldHeader, 15);
		objFormatter.addField(TaskFieldCustomizer.getInstance().getDisplayFieldDelimiter(), 2);
		objFormatter.addField(pstrFieldData, 1);
		pobjSB.append(objFormatter.toString());
		pobjSB.append(Utils.getLineSeparator());
	}
	
	// facilitators
	
	/**
	 * Writes properties to file. For future use.
	 */	
	public String setProperties() {
		Properties objProperties = new Properties();
		try {
			objProperties.load(new FileInputStream(CONFIG_FILENAME));
			objProperties.put(CONFIG_FIELD_SENDER_HOST, _strSendingHost);
			objProperties.put(CONFIG_FIELD_SENDER_PORT, _strSendingPort);
			objProperties.put(CONFIG_FIELD_SENDER_EMAIL_ADDRESS, _strSendingEmailAdd);
			objProperties.put(CONFIG_FIELD_SENDER_PASSWORD, _strSendingPassword);
			objProperties.put(CONFIG_FIELD_RECEIVER_EMAIL_ADDRESS, _strReceivingEmailAdd);
			objProperties.put(CONFIG_FIELD_TIMEOUT, String.valueOf(_intTimeout));
			FileOutputStream objFOS = new FileOutputStream("config.props");
			objProperties.store(objFOS, "");
			objFOS.close();
			return null;
		} catch (FileNotFoundException objEx) {
			_strError = ErrorMessages.ERR_CONFIG_FILE_NOT_FOUND;
			return _strError;
		} catch (IOException objEx) {
			_strError = ErrorMessages.ERR_CONFIG_FILE_UNABLE_TO_OPEN;
			return _strError;
		}
	}
	
	// getters

	public String getSendingHost() {
		return _strSendingHost;
	}

	public String getSendingPort() {
		return _strSendingPort;
	}

	public String getSendingEmailAdd() {
		return _strSendingEmailAdd;
	}
	
	public String getSendingPassword() {
		return _strSendingPassword;
	}
	
	public String getReceivingEmailAdd() {
		return _strReceivingEmailAdd;
	}
	
	public int getTimeout() {
		return _intTimeout;
	}
	
	public String getError() {
		return _strError;
	}
	
	// setters

	public void setSendingHost(String pstrInput) {
		_strSendingHost = pstrInput;
	}

	public void setSendingPort(String pstrInput) {
		_strSendingPort = pstrInput;
	}

	public void setSendingEmailAdd(String pstrInput) {
		_strSendingEmailAdd = pstrInput;
	}
	
	public void setSendingPassword(String pstrInput) {
		_strSendingPassword = pstrInput;
	}
	
	public void setReceivingEmailAdd(String pstrInput) {
		_strReceivingEmailAdd = pstrInput;
	}
	
	public void setTimeout(int pintInput) {
		_intTimeout = pintInput;
	}
	
	// overrides
	
	@Override
	public String toString() {
		if (_strError != null)
			return _strError;
		StringBuffer objSB = new StringBuffer(500);
		insertFieldLine(objSB, "Email Host", _strSendingHost);
		insertFieldLine(objSB, "Email Port", _strSendingPort);
		insertFieldLine(objSB, "Sender Email", _strSendingEmailAdd);
		insertFieldLine(objSB, "Sender Password", "***");
		insertFieldLine(objSB, "Receiver Email", _strReceivingEmailAdd);
		insertFieldLine(objSB, "Timeout", String.valueOf(_intTimeout));
		return objSB.toString();
	}
	
}
